import React, {
  FC,
  useState,
  useEffect,
  ChangeEvent,
  useRef,
  ReactElement,
  KeyboardEvent
} from "react";
import Input, { BaseInputProps } from "../Input/input";
import Icon from "../Icon/icon";
import useDebonce from "../hooks/useDebonce";
import classNames from 'classnames'
import useClickOutside from '../hooks/useClickOutside'
// 这是一个下拉筛选框，主体由一个Input框和 下拉选项组成，有筛选功能和选中功能

interface DataSourceObject {
  value: string;
  [propName: string]: any;
  // num:number
}
export type DataSourceType<T = DataSourceObject> = DataSourceObject; //T

export interface AutoCompleteProps extends Omit<BaseInputProps, "onSelect"> {
  //因为input组件中的onSelect和这里的onSelect冲突，所以忽略input的onSelect
  fetchSuggestions: (
    str: string
  ) => DataSourceType[] | Promise<DataSourceType[]>; //用于做同步或异步筛选
  onSelect?: (item: DataSourceType) => void;
  renderOption?: (item: DataSourceType) => ReactElement;
}

export const AutoComplete: FC<AutoCompleteProps> = (props) => {
  const {
    fetchSuggestions,
    value,
    onSelect,
    renderOption,
    ...restProps
  } = props;
  const [inputValue, setInputValue] = useState(value as string);
  const [loading, setLoading] = useState(false);
  const [suggestions, setSugestions] = useState<DataSourceType[]>([]);
  const debonceValue = useDebonce(inputValue, 1000);
  
  const triggerSearch = useRef(false);
  const componentRef=useRef<HTMLDivElement>(null)
  const [highlightIndex,setHighlightIndex]=useState(-1)

  useClickOutside(componentRef,()=>{
    setSugestions([])
  })
  useEffect(() => {
    
    if (debonceValue && triggerSearch.current) {
      let result = fetchSuggestions(debonceValue);
      if (result instanceof Promise) {
        setLoading(true);
        result.then((data) => {
          setLoading(false);
          setSugestions(data);
        });
      } else {
        setSugestions(result);
      }
      setHighlightIndex(-1);//每次输入文字都更新高亮
    } else {
      //如果筛选出结果，就设置为空数组
      setSugestions([]);
    }
  }, [debonceValue]);
  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value.trim();
    setInputValue(value);
    triggerSearch.current = true;

  };
  const handleSelect = (item: DataSourceType) => {
    setInputValue(item.value);

    setSugestions([]);
    if (onSelect) {
      onSelect(item);
    }
    triggerSearch.current = false;
  };

  const renderTemplate = (item: DataSourceType) => {
    return renderOption ? renderOption(item) : item;
  };
  const generateDropdown = () => {
    return (
      <ul>
        {suggestions.map((item, index) => {
          const cnames=classNames('suggestions-item',{
            'item-highlighted':index===highlightIndex
          })
          return (
            <li className={cnames} key={index} onClick={() => handleSelect(item)}>
              {renderTemplate(item)}
            </li>
          );
        })}
      </ul>
    );
  };
  const highlight=(index: number)=>{
    
    if(index<0) index=suggestions.length-1;
    if(index>=suggestions.length){
      index=0;
    }
    console.log(index)
    setHighlightIndex(index);
  }
  //键盘事件
  const handleKeyDown=(e: KeyboardEvent<HTMLElement>)=>{
    switch(e.keyCode){
      case 13://回车
        if(suggestions[highlightIndex]){
          handleSelect(suggestions[highlightIndex]);
        }
        break;
      case 38://上键
       highlight(highlightIndex-1);break;
      case 40://下键
        highlight(highlightIndex+1);break;
      case 27://esc
        setSugestions([]);break;
      default:
        break;
    }
  }
  return (
    <div className="zs-auto-complete" ref={componentRef}>
      <Input value={inputValue} 
      onChange={handleChange} 
      onKeyDown={handleKeyDown}
      {...restProps} />
      {loading && (
        <ul>
          <Icon icon="spinner" spin />
        </ul>
      )}
      {suggestions.length > 0 && generateDropdown()}
    </div>
  );
};

export default AutoComplete;
